/*
 * Liscense: 	GPL http://www.gnu.org/copyleft/gpl.html
 * By: 		A. Tres Finocchiaro
 * Date:	2007
 * Java:	6.0SE
 */
package com.pentajock.docdb;

//import com.pentajock.docdb.utils.DocumentFileFilter;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.net.*;
import java.sql.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import com.jacob.activeX.ActiveXComponent;
import com.pentajock.docdb.database.*;
import com.pentajock.docdb.dialogs.*;
import com.pentajock.docdb.gui.*;
import com.pentajock.docdb.images.DBImages;
import com.pentajock.docdb.lang.Lang;
import com.pentajock.docdb.listeners.FileDrop;
import com.pentajock.docdb.office.*;
import com.pentajock.docdb.types.*;
import com.pentajock.docdb.utils.*;


public class ClientWindow extends JFrame {
	static private final String SEARCH_INPUT_KEY = "SEARCH_KEY";
	static private final int NUM_BUTTON_ROWS = 2;
	static private final int NUM_BUTTON_COLS = 4;
	static private final int BUTTON_HORIZONTAL_GAP = 8;
	static private final int BUTTON_VERTICAL_GAP = 8;
	static private final Dimension minimumSize = new Dimension(625, 500);
	static private final Dimension anySize = new Dimension(150,75);
	static private final String COLON = Lang.MISC.getText("CHOICE_DELIMITER", ":");
	
	
	/*
	 * Primary UI components
	 */
	private DocumentResultListModel resultListModel;
	private VisibleIndexList resultList;
	private JButton oweButton;
	private JButton sendBackButton;
	private JButton renameButton;
	private JButton newButton;
	private JButton searchButton;
	private JButton addNotesButton;
	private JButton listAllButton;
	private JButton editOrViewButton;
	private JPanel buttonPanel;
	/**/
	
	/*
	 * Menu items
	 */
	// Menu Bar items
	private JMenuItem logoutMenuItem;
	private JMenuItem exitMenuItem;
	private JMenuItem searchMenuItem;
	private JMenuItem shortcutMenuItem;
	private JMenuItem changePassMenuItem;
	private JMenuItem printMenuItem;
	private JMenuItem switchToAdminMenuItem;
	private JMenuItem egoAssignMenuItem;
	private JMenuItem listOweMenuItem;
	private JMenuItem listAllMenuItem;
	private JMenuItem copyToDesktopMenuItem;
	private JMenuItem linkToDocumentMenuItem;
	private JMenuItem createNewMenuItem;
	private JMenuItem aboutMenuItem;
	private JCheckBoxMenuItem hideButtonPanelMenuItem;
	private JCheckBoxMenuItem decorateBorderMenuItem;
	// Popup items
	private JPopupMenu listPopupMenu; // The popup menu itself.
	private JMenuItem editOrViewPopupItem;
	private JMenuItem sendBackPopupItem;
	private JMenuItem addNotesPopupItem;
	private JMenuItem renamePopupItem;
	private JMenuItem deletePopupItem;
	private JMenuItem printPopupItem;
	private JMenuItem egoAssignPopupItem;
	/**/
	
	/*
	 * Action references.
	 */
	private Action listOweAction;
	private Action sendBackAction;
	private Action renameAction;
	private Action newAction;
	private Action searchAction;
	private Action addNotesAction;
	private Action listAllAction;
	private Action logoutAction;
	private Action exitAction;
	private Action editAction;
	private Action viewAction;
	private Action deleteAction;
	private Action shortcutAction;
	private Action changePassAction;
	private Action printFromOweAction;
	private Action printFromDBAction;
	private Action switchToAdminAction;
	private Action hideButtonPanelAction;
	private Action egoAssignAction;
	private Action decorateBorderAction;
	private Action copyToDesktopAction;
	private Action linkToDocumentAction;
	private Action aboutAction;
	/**/
	
	private ListRenderer listRenderer;
	private SearchDialog searchDialog;
	private StatusBar statusBar;
	private boolean userLoggedIn;
	private boolean userIsAdmin;
	private User currentUser;
	private String userName;
	private String departmentName;
        private DocumentFileFilter docFilter;
	
	public ClientWindow() {
		super(Main.DEFAULT_TITLE);
		userLoggedIn = false;
		userIsAdmin = false;
		userName = "noshow";
		
		createActions();
		initializeUIComponents();
		layoutFrame();
		buildMenus();
		addListeners();
		hideButtonPanel(!Main.userIni.getBooleanProperty("View", "hide_button_panel"));
		decorateBorderMenuItem.setSelected(Main.userIni.getBooleanProperty("User Interface", "decorated"));
		setIconImage(DBImages.CLIENT_WINDOW.getImage());
		setPreferredSize(Utils.getBestSize(this, minimumSize));
		setMinimumSize(!buttonPanel.isVisible()? anySize : minimumSize);
		pack();
		setLocationRelativeTo(null);
                Main.printDebug("ClientWindow loaded to memory.");
	}
	
	private void createActions() {
		viewAction = new AbstractAction(Lang.BUTTON.getText("VIEW", "View"), DBImages.DOC_OPEN_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				if(resultList.getSelectedIndex() != -1) {
					if(!resultList.getSelectedValue().toString().startsWith("~")) {
						Main.setCursor(ClientWindow.this, Cursor.WAIT_CURSOR);
						openDocumentReadOnly(resultList.getSelectedValue(), true);
					}
					Main.setCursor(ClientWindow.this, Cursor.DEFAULT_CURSOR);
				}
			}
		};
		viewAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_V);
		viewAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("VIEW"));
		
		editAction = new AbstractAction(Lang.BUTTON.getText("EDIT", "Edit"), DBImages.DOC_EDIT_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				if(resultList.getSelectedIndex() != -1) {
					Main.setCursor(ClientWindow.this, Cursor.WAIT_CURSOR);
					openDocumentEdit(resultList.getSelectedValue(), currentUser, true);
					Main.setCursor(ClientWindow.this, Cursor.DEFAULT_CURSOR);
				}
			}
		};
		
		
		editAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_E);
		editAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("EDIT"));
		
		copyToDesktopAction = new AbstractAction(Lang.MENU.getText("COPY_DESKTOP", "Copy to Desktop") + COLON, DBImages.DOC_DESKTOP_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				copyDocToDesktop();
			}
		};
		copyToDesktopAction.putValue(Action.MNEMONIC_KEY, Lang.MENU.getMnemonic("COPY_DESKTOP", KeyEvent.VK_C));
		
		
		listOweAction = new AbstractAction(Lang.BUTTON.getText("LIST_OWE", "What Do I Owe?"), DBImages.DOC_ASSIGNED_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				listOwedDocs(userName);
			}
		};
		listOweAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("LIST_OWE"));
		listOweAction.putValue(Action.MNEMONIC_KEY, Lang.MENU.getMnemonic("LIST_OWE", KeyEvent.VK_O));
		listOweAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0));
		
		aboutAction = new AbstractAction(Lang.MENU.getText("ABOUT", "About"), DBImages.BULB_ICON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Dialogs.showAboutDialog();
			}
		};
		
		sendBackAction = new AbstractAction(Lang.BUTTON.getText("SEND_BACK", "Send Back"), DBImages.DOC_SEND_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				if(resultList.getSelectedIndex() != -1) {
					sendBackDocument(resultList.getSelectedValue());
				}
			}
		};
		sendBackAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_B);
		sendBackAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("SEND_BACK"));
		
		renameAction = new AbstractAction(Lang.BUTTON.getText("RENAME", "Rename"), DBImages.DOC_RENAME_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Document d;
				Object o = resultList.getSelectedValue();
				if (o instanceof Document)
					d = ((Document)o);
				else
					return;
				
				File newFile = promptForRename(d.toAssignedFile(currentUser));
				if (renameDocument(d.toAssignedFile(currentUser), newFile)) {
					DBController.renameDocument(d, newFile);
					listOwedDocs(userName);
					resultList.setSelectedValue(newFile, true);
					resultList.requestFocusInWindow();
				}
			}
		};
		renameAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R);
		renameAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("RENAME"));
		
		newAction = new AbstractAction(Lang.BUTTON.getText("CREATE_NEW", "Create New"), DBImages.DOC_ADD_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {	
				createNewDocument();
			}
		};
		newAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_N);
		newAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("CREATE_NEW"));
		newAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
		
		deleteAction = new AbstractAction("Delete", DBImages.REMOVE_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				if(resultList.getSelectedIndex() != -1) {
					deleteSelectedItem(true);
				}
			}
		};
		
		linkToDocumentAction = new AbstractAction(Lang.BUTTON.getText("COPY_LINK", "Copy Link"), DBImages.DOC_LINK_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Object o = resultList.getSelectedValue();
				Document d;
				if (o instanceof Document)
					d = (Document)o;
				else
					return;
				
				if (Klipboard.createLink(d))
					Dialogs.showSuccess(d.toFile().toURI(), "Copied the following link to your clipboard:", 
						null, "\nYou can now paste this into an application that supports rich text");
							/*Dialogs.showSuccess("<HTML>Copied the following link to your clipboard:<BR><UL>" +
							"<A HREF=\"about:blank\">" + resultList.getSelectedValue().toString() +
							"</A></UL><BR>You can now paste this into an application " + 
							"that supports rich text.</HTML>");*/
				else
					Dialogs.showError("Error creating a clipboard link to this document");
			}
		};
		linkToDocumentAction.putValue(Action.MNEMONIC_KEY, Lang.BUTTON.getMnemonic("COPY_LINK", KeyEvent.VK_C));
		
		deleteAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_D);
		deleteAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
		deleteAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("DELETE"));
		
		searchAction = new AbstractAction(Lang.BUTTON.getText("SEARCH", "Search"), DBImages.SEARCH_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				searchDocuments(promptForSearch());
			}
		};
		searchAction.putValue(Action.MNEMONIC_KEY, Lang.BUTTON.getMnemonic("SEARCH", KeyEvent.VK_S));
		searchAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK));
		searchAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("SEARCH"));
		
		addNotesAction = new AbstractAction(Lang.BUTTON.getText("ADD_NOTES", "Add Notes"), DBImages.DOC_ADD_NOTES_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				//
			}
		};
		
		addNotesAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_A);
		addNotesAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("ADD_NOTES"));
		
		listAllAction = new AbstractAction(Lang.BUTTON.getText("LIST_ALL", "List All"), DBImages.DOC_LIST_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Main.setCursor(ClientWindow.this, Cursor.WAIT_CURSOR);
				listAllDocs(null);
				Main.setCursor(ClientWindow.this, Cursor.DEFAULT_CURSOR);
			}
		};
		listAllAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_L);
		listAllAction.putValue(Action.SHORT_DESCRIPTION, Lang.TOOL_TIP.get("LIST_ALL"));
		listAllAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0));
		
		logoutAction = new AbstractAction(Lang.MENU.getText("LOG_OUT", "Log Out"), DBImages.LOGOUT_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				logoutUser();
			}
		};
		logoutAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_L);
		logoutAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_L, InputEvent.CTRL_MASK));
		
		exitAction = new AbstractAction(Lang.MENU.getText("EXIT", "Exit"), DBImages.EXIT_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				closeProgram();
			}
		};
		exitAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_X);
		exitAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
		
		shortcutAction = new AbstractAction(Lang.MENU.getText("DESKTOP_ICON", "Create Desktop Icon"), DBImages.SHORTCUT_ICON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				DesktopIconFactory.createDesktopIcon(".images", Lang.MISC.getText("TITLE", "Document Database"), "DBClient.jar");
			}
		};
		shortcutAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_D);
		
		changePassAction = new AbstractAction(Lang.MENU.getText("PASSWORD", "Change Password"), DBImages.KEY_ICON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				PasswordDialog changePasswordDialog = new PasswordDialog(ClientWindow.this);
				changePasswordDialog.setUser(userName);
				changePasswordDialog.setVisible(true);
			}
		};
		changePassAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
		
		printFromOweAction = new AbstractAction(Lang.MENU.getText("PRINT", "Print"), DBImages.PRINT_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Object o = resultList.getSelectedValue();
				if (o instanceof Document)
					Jacob.printDocument(((Document)o).toAssignedFile(currentUser));
				else if (o instanceof File)
					Jacob.printDocument((File)o);
			}
		};
		printFromOweAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_P);
		printFromOweAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK));
		
		printFromDBAction = new AbstractAction(Lang.MENU.getText("PRINT", "Print"), DBImages.PRINT_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Object o = resultList.getSelectedValue();
				if (o instanceof Document)
					Jacob.printDocument((Document)o);
				else if (o instanceof File)
					Jacob.printDocument((File)o);
			}
		};
		printFromDBAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_P);
		printFromDBAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK));
		
		switchToAdminAction = new AbstractAction(Lang.MENU.getText("ADMIN_VIEW", "Admin view"), DBImages.ADMIN_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Main.setCursor(ClientWindow.this, Cursor.WAIT_CURSOR);
				AdminWindow adminWindow = new AdminWindow(currentUser);
				adminWindow.setVisible(true);
				dispose();
			}
		};
		switchToAdminAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_A);
		switchToAdminAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
		
		hideButtonPanelAction = new AbstractAction(Lang.MENU.getText("SHOW_BUTTONS", "Show button panel"), DBImages.PANEL_ICON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				hideButtonPanel(hideButtonPanelMenuItem.isSelected());
			}
		};
		hideButtonPanelAction.putValue(Action.MNEMONIC_KEY, Lang.MENU.getMnemonic("SHOW_BUTTONS", KeyEvent.VK_S));
		hideButtonPanelAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_MASK));
		
		decorateBorderAction = new AbstractAction(Lang.MENU.getText("SHOW_BORDER", "Show theme window borders"), DBImages.GUI_XP_ICON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				Main.userIni.setBooleanProperty("User Interface", "decorated", decorateBorderMenuItem.isSelected());
				Dialogs.showSuccess("This will not take effect until the program is restarted.");
			}
		};
		decorateBorderAction.putValue(Action.MNEMONIC_KEY, Lang.MENU.getMnemonic("SHOW_BORDER", KeyEvent.VK_D));
		
		egoAssignAction = new AbstractAction(Lang.MENU.getText("EGO_ASSIGN", "Assign to myself"), DBImages.DOC_SEND_BUTTON.getIcon()) {
			public void actionPerformed(ActionEvent e) {
				egoAssignDocument();
			}
		};
		egoAssignAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_G);
		egoAssignAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.CTRL_MASK));
	}
	
	private void initializeUIComponents() {
		listRenderer = new ListRenderer();
		searchDialog = new SearchDialog(this);
		statusBar = new StatusBar(this);
		resultListModel = new DocumentResultListModel();
		resultList = new VisibleIndexList(resultListModel);
		resultList.setCellRenderer(listRenderer);
		oweButton = new JButton(listOweAction);
		sendBackButton = new JButton(sendBackAction);
		renameButton = new JButton(renameAction);
		newButton = new JButton(newAction);
		searchButton = new JButton(searchAction);
		addNotesButton = new JButton(addNotesAction);
		listAllButton = new JButton(listAllAction);
		editOrViewButton = new JButton(editAction);
	}
	
	private void layoutFrame() {
		JScrollPane resultListScroll = new JScrollPane(resultList);
		resultListScroll.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		
		buttonPanel = new JPanel(new GridLayout(NUM_BUTTON_ROWS, NUM_BUTTON_COLS, BUTTON_HORIZONTAL_GAP, BUTTON_VERTICAL_GAP));
		buttonPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
		buttonPanel.add(oweButton);
		buttonPanel.add(renameButton);
		buttonPanel.add(searchButton);
		buttonPanel.add(listAllButton);
		buttonPanel.add(sendBackButton);
		buttonPanel.add(newButton);
		buttonPanel.add(addNotesButton);
		buttonPanel.add(editOrViewButton);

		GridBagLayout gridBag = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		JPanel upperPanel = new JPanel(gridBag);
		
		/*
		 * Layout constraints for resultListScroll
		 */
		c.gridx = 0;
		c.gridy = 0;
		c.weightx = 1.0;
		c.weighty = 1.0;
		c.fill = GridBagConstraints.BOTH;
		
		gridBag.setConstraints(resultListScroll, c);
		upperPanel.add(resultListScroll);
		
		/*
		 * Layout constraints for buttonPanel
		 */
		c.gridx = 0;
		c.gridy = 1;
		c.weightx = 0.0;
		c.weighty = 0.0;
		c.fill = GridBagConstraints.NONE;
		
		gridBag.setConstraints(buttonPanel, c);
		upperPanel.add(buttonPanel);
		
		getContentPane().add(upperPanel, BorderLayout.CENTER);
		getContentPane().add(statusBar, BorderLayout.SOUTH);
	}
	
	private void buildMenus() {
		/*
		 * Setup the Menu Items
		 */
		exitMenuItem = new JMenuItem(exitAction);
		logoutMenuItem = new JMenuItem(logoutAction);
		searchMenuItem = new JMenuItem(searchAction);
		listAllMenuItem = new JMenuItem(listAllAction);
		listOweMenuItem = new JMenuItem(listOweAction);
		shortcutMenuItem = new JMenuItem(shortcutAction);
		printMenuItem = new JMenuItem(printFromOweAction);
		egoAssignMenuItem = new JMenuItem(egoAssignAction);
		changePassMenuItem = new JMenuItem(changePassAction);
		switchToAdminMenuItem = new JMenuItem(switchToAdminAction);
		copyToDesktopMenuItem = new JMenuItem(copyToDesktopAction);
		decorateBorderMenuItem = new JCheckBoxMenuItem(decorateBorderAction);
		hideButtonPanelMenuItem = new JCheckBoxMenuItem(hideButtonPanelAction);
		linkToDocumentMenuItem = new JMenuItem(linkToDocumentAction);
		createNewMenuItem = new JMenuItem(newAction);
		aboutMenuItem = new JMenuItem(aboutAction);
		/*
		 * Create Menu Bar menus
		 */
		JMenu fileMenu = new JMenu(Lang.MENU.getText("FILE", "File"));
		fileMenu.setMnemonic(Lang.MENU.getMnemonic("FILE", KeyEvent.VK_F));
		fileMenu.add(switchToAdminMenuItem);
		fileMenu.add(printMenuItem);
		fileMenu.add(logoutMenuItem);
		fileMenu.add(new JSeparator());
		fileMenu.add(exitMenuItem);
		
		JMenu viewMenu = new JMenu(Lang.MENU.getText("VIEW", "View"));
		viewMenu.setMnemonic(Lang.MENU.getMnemonic("VIEW", KeyEvent.VK_V));
		viewMenu.add(listOweMenuItem);
		viewMenu.add(listAllMenuItem);
		viewMenu.add(new JSeparator());
		viewMenu.add(hideButtonPanelMenuItem);
		viewMenu.add(decorateBorderMenuItem);
		viewMenu.add(new JSeparator());
		viewMenu.add(Utils.buildThemesMenu(this));
		viewMenu.add(Utils.buildColorsMenu(this));
		
		JMenu utilityMenu = new JMenu(Lang.MENU.getText("UTILITIES", "Utilities"));
		utilityMenu.setMnemonic(Lang.MENU.getMnemonic("UTILITIES", KeyEvent.VK_U));
		utilityMenu.add(searchMenuItem);
		utilityMenu.add(egoAssignMenuItem);
		utilityMenu.add(createNewMenuItem);
		utilityMenu.add(linkToDocumentMenuItem);
		utilityMenu.add(copyToDesktopMenuItem);
		utilityMenu.add(new JSeparator());
		utilityMenu.add(changePassMenuItem);
		utilityMenu.add(shortcutMenuItem);
		utilityMenu.add(new JSeparator());
		utilityMenu.add(Utils.buildLanguageMenu());
		
		JMenu helpMenu = new JMenu(Lang.MENU.getText("HELP", "Help"));
		helpMenu.setMnemonic(Lang.MENU.getMnemonic("HELP", KeyEvent.VK_H));
		helpMenu.add(aboutMenuItem);
		
		JMenuBar menuBar = new JMenuBar();
		menuBar.add(fileMenu);
		menuBar.add(viewMenu);
		menuBar.add(utilityMenu);
		menuBar.add(helpMenu);
		
		setJMenuBar(menuBar);
		
		/*
		 * Create Popup Menu
		 */
		editOrViewPopupItem = new JMenuItem(viewAction);
		sendBackPopupItem = new JMenuItem(sendBackAction);
		addNotesPopupItem = new JMenuItem(addNotesAction);
		renamePopupItem = new JMenuItem(renameAction);
		deletePopupItem = new JMenuItem(deleteAction);
		printPopupItem = new JMenuItem(printFromOweAction);
		egoAssignPopupItem = new JMenuItem(egoAssignAction);
		
		listPopupMenu = new JPopupMenu();
		listPopupMenu.add(editOrViewPopupItem);
		listPopupMenu.add(sendBackPopupItem);
		listPopupMenu.add(addNotesPopupItem);
		listPopupMenu.add(renamePopupItem);
		listPopupMenu.add(printPopupItem);
		listPopupMenu.add(egoAssignPopupItem);
		listPopupMenu.add(new JSeparator());
		listPopupMenu.add(deletePopupItem);

		
		listPopupMenu.pack();
	}
	
	private void addListeners() {
		addWindowListener(new WindowAdapter() {
			@Override
                        public void windowClosing(WindowEvent e) {
				exitAction.actionPerformed(null);
			}
		});
		
		
		resultList.addMouseListener(new MouseAdapter() {
			@Override
                        public void mouseClicked(MouseEvent e) {
				if(e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
					editOrViewButton.getAction().actionPerformed(null);
				}
			}
			@Override
			public void mousePressed(MouseEvent e) {
				if(e.isPopupTrigger()) {
					showListPopupMenu(e.getPoint());
				}
			}
			@Override
			public void mouseReleased(MouseEvent e) {
				if(e.isPopupTrigger()) {
					showListPopupMenu(e.getPoint());
				}
			}
		});
		
		resultList.addKeyListener(new KeyAdapter() {
			@Override
                        public void keyPressed(KeyEvent e) {
				switch(e.getKeyCode()) {
				case KeyEvent.VK_DELETE:
					if(deleteAction.isEnabled()) {
						deleteAction.actionPerformed(null);
					}
					break;
				case KeyEvent.VK_ENTER:
					editOrViewButton.getAction().actionPerformed(null);
					break;
				default:
				}
			}
		});
		
		new FileDrop(resultList, /*dragBorder,*/ new FileDrop.Listener() {
			public void filesDropped(File[] files) {
				File lastFile = null;
				int goodFileCount = 0;
				for (File i : files) {
					try {
						if (DBController.isSupportedFile(i)) {
							if (Utils.copyFile(i.getCanonicalPath(), Utils.getUserRoot(userName) + i.getName())) {
								goodFileCount++;
								DBController.addDocument(Utils.createDocument(i, userName), userName);
								lastFile = i;
								
							}
						}
					}
					catch(IOException e) {}
				}
				if (goodFileCount > 0) {
					listOwedDocs(userName);
					statusBar.setLabelText(goodFileCount + " " + Lang.STATUS_BAR.getText("FILE_ADDED", "file(s) added."));
					resultList.setSelectedValue(lastFile.getName(), true);
					
				}
				else 
					statusBar.setLabelText(Lang.MISC.get("DOCUMENT", "document") + " " + 
						lastFile.getName() + " " +
						Lang.STATUS_BAR.get("NOT_SUPPORTED", "not supported"));
			}
		});
		
		/*
		 * Set up sort-of global hotkeys that are neither handled through
		 * mnemonics nor accelerators already.
		 */
		InputMap inputMap = new ComponentInputMap((JComponent)getContentPane());
		inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, 0), SEARCH_INPUT_KEY);
		
		ActionMap actionMap = new ActionMap();
		actionMap.put(SEARCH_INPUT_KEY, searchAction);
		
		((JComponent)getContentPane()).setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
		((JComponent)getContentPane()).setActionMap(actionMap);
		/**/
	}
	
	private void showListPopupMenu(Point p) {
		resultList.setSelectedIndex(resultList.locationToIndex(p));
		listPopupMenu.show(resultList, p.x, p.y);
	}
	
	private void hideButtonPanel(boolean isHidden) {
		buttonPanel.setVisible(isHidden);
		hideButtonPanelMenuItem.setSelected(isHidden);
		Main.userIni.setBooleanProperty("View", "hide_button_panel", !isHidden);
		setMinimumSize(isHidden ? minimumSize : new Dimension(0,0));
	}
	
	/**
	 * Given the username of the person logging in.
	 * Sets the window's title and resets the interface.
	 */
	 public void loginUser(User u) throws SQLException {
		loginUser(u.getUserName());	 
	 } 
	 
	 public void loginUser(String userName) throws SQLException {
		/* 
		 * Do query stuff all at once in case of SQLException, it will
		 * break and hopefully won't hurt anything.
		 */
		Main.printDebug("Logging in user: " + userName);
		currentUser = DBController.getUser(userName);
		if (currentUser == null) 
			return; 
		
		String firstName = currentUser.getFirstName();
		String lastName = currentUser.getLastName();
		userIsAdmin = currentUser.isAdmin();
		Jacob.setUserName(userName);
		Utils.resetRoots();
		
		userLoggedIn = true;
		this.userName = userName;
		departmentName = DBController.getUserDepartment(userName);

		setTitle(Lang.MISC.getText("TITLE", Main.DEFAULT_TITLE) + " - " + firstName + " " + lastName);
		listRenderer.setUserName(userName);
		listOwedDocs(userName);
		setLocationRelativeTo(null);
		
		setVisible(true);
		if(userIsAdmin) {
			setIconImage(DBImages.ADMIN_WINDOW.getImage());
			switchToAdminAction.setEnabled(true);
		}
		else {
			setIconImage(DBImages.CLIENT_WINDOW.getImage());
			switchToAdminAction.setEnabled(false);	
		}
	}
	
	private void logoutUser() {
		Main.printDebug("Logging out user: " + userName);
		userName = null;
		userLoggedIn = false;
		resultListModel.clear();
		setTitle(Main.DEFAULT_TITLE);
		setVisible(false);
	}
        
	private void showLoginDialog() {
		//LoginFrame loginDialog = new LoginFrame();
                LoginDialog loginDialog = new LoginDialog();
		loginDialog.setVisible(true);
		if(loginDialog.isCanceled()) {
			closeProgram();
		}
		else {
			try {
				loginUser(loginDialog.getUserName());
			}
			catch(SQLException ex) {
				Main.printStackTrace(ex, "SQL Error at login.");
				JOptionPane.showMessageDialog(this, Lang.DIALOG.get("LOGIN_ERROR"),
					Lang.DIALOG.get("ERROR_TITLE", "Error"), JOptionPane.ERROR_MESSAGE);
				logoutUser();
			}
		}
	}
	
	private void closeProgram() {
		DBController.close();
		Main.userIni.setIntegerProperty("View", "client_window_width", getWidth());
		Main.userIni.setIntegerProperty("View", "client_window_height", getHeight());
		Main.sysIni.updateFile();
		Main.userIni.updateFile();
		DBController.stopInternalDatabase(); // If running :)
		// Insert any other needed shutdown related code before here.
		System.exit(0);
	}
	
        @Override
	public void setVisible(boolean b) {
		/*
		 * Below is the code that makes the application disappear and
		 * with the help of the custom LoginFrame, only the dialog
		 * will be visible and will also appear in the taskbar.
		 */
		if(b && userLoggedIn) {
			super.setVisible(b);
		}
		else {
			super.setVisible(false);
			showLoginDialog();
		}
	}
	
	/**
	 * Searches through a list of file servers stored in the database
	 * and returns any documents with supported extensions that meet
	 * the search criteria.  This is only performed if the "search file 
	 * servers" checkbox is checked.  This does not currently recurse
	 * through folders.
	 */
	private void searchFileServers(Set<String> wordSet, String searchPhrase, Set<WeightedDocument> weightedResults) {
		Main.setCursor(this, Cursor.WAIT_CURSOR);
		//DocumentFileFilter ff = new DocumentFileFilter();
		for (String s : DBController.getFileServers()) {
			File[] extraFiles;
			try {
				File f = new File(new URI(s));
				if (f.exists() && f.isDirectory()) {
					extraFiles = f.listFiles(docFilter);
					Arrays.sort(extraFiles);
					for (File e : extraFiles) {
						Integer relevanceCounter = 0;
						for(String searchTerm : wordSet)
							if (e.getName().toLowerCase().contains(searchTerm.toLowerCase()))
								relevanceCounter++;
						if (relevanceCounter > 0) 
							weightedResults.add(new WeightedDocument(e, relevanceCounter));
					}
				}
			}
			catch (Exception e) {
				Main.printStackTrace(e, "Can't list files on " + s);
			}
		}
		listWeightedResults(weightedResults);
		Main.setCursor(this, Cursor.DEFAULT_CURSOR);
	}
	
	private boolean deleteSelectedItem(boolean promptUser) {
		Object o = resultList.getSelectedValue();
		int i = resultList.getSelectedIndex();
		File f = null;
		Document d = null;
		if (o instanceof Document) {
			d = (Document)o;
			f = new File(Utils.getUserRoot(currentUser) + d.getFullName());
		}
		else
			return false;
		
		if (d != null && d.isApproved())
			Dialogs.showError(o, Lang.DIALOG.get("DOCUMENT_DELETE_ACCESS", "You do not have proper authority to delete this document"));
		else if (f != null) {
			if (!promptUser || Dialogs.confirmDelete(o)) {
				if (f.delete()) {
					DBController.deleteDocument(d);
					listOwedDocs(userName);
					resultList.setSelectedIndex(i);
					Dialogs.showSuccess(o, Lang.DIALOG.get("DOCUMENT_DELETE_SUCCESS", "Successfully deleted document"));
					return true;
				}
				else
					Dialogs.showError(o, Lang.DIALOG.get("DOCUMENT_DELETE_ERROR", "Deletion failed"));
			}
		}
		else
			Main.printDebug("File \"" + f + "\" was not deleted.");
		return false;
	}
	
	private void egoAssignDocument() {
		Object o = resultList.getSelectedValue();
		if (o instanceof Document) {
			Document d = (Document)o;
			
			String toUser = Lang.MISC.getText("TO", "to");
			String assignSuccess = Lang.DIALOG.getText("ASSIGN_SUCCESS", "Successfully assigned");
			String deptError = Lang.DIALOG.getText("ASSIGN_DEPT_ERROR", "Wrong department") + COLON + " (" + d.getDepartmentName() + ")";
			String copyError = Lang.DIALOG.getText("ASSIGN_COPY_ERROR", "Assign copy error");
			
			if (departmentName.equalsIgnoreCase(d.getDepartmentName())) {
				File fDest = new File(Utils.getUserRoot(currentUser) + d.getFullName());		
				if (DBController.assignDocument(d, currentUser)) {
					try {
						if (Utils.copyFile(d.toFile(), fDest))
							Dialogs.showSuccess(d, assignSuccess, currentUser, toUser);
						else
							throw new IOException(d.toFile() + " could not be copied");
					}
					catch (IOException ex) {
						Dialogs.showError(ex, d, copyError);
					}
				}
			}
			else
				Dialogs.showError(d, deptError);
		}
		else {
		  	Dialogs.showError(o, Lang.DIALOG.get("ASSIGN_TYPE_ERROR", "Wrong document type"));
		}
		 
	}
	
	private File promptForRename(File currentFile) {
		String msg = Lang.DIALOG.getText("DOCUMENT_NEW_NAME", "Please type the new name for this document:");
		String defaultName = Lang.DIALOG.getText("DOCUMENT_DEFAULT_NAME", "SYSTEMNAME - Document Name");
		String delim = " " + Lang.MISC.getText("NAME_DELIMITER", "-") + " ";
		String ext = "." + Utils.getExtension(currentFile);
		
		String newName;
		if (currentFile.getName().startsWith("~"))
			newName = Dialogs.showInputDialog(departmentName.toUpperCase() + delim + defaultName, msg);
		else
			newName = Dialogs.showInputDialog(currentFile, msg);
		if (newName == null)
			return null;
		return new File(Utils.getUserRoot(userName) + 
			(newName.toLowerCase().endsWith(ext)?newName:newName+ext));
	}
	
	private void copyDocToDesktop() {
		Object o = resultList.getSelectedValue();
		boolean success = false;
		File fSrce;
		File fDest;
		if (o instanceof Document) {
			fSrce = ((Document)o).toAssignedFile(currentUser);
		}
		else {
			return;
		}
		
		fDest = new File(System.getProperty("user.home").toLowerCase() + "/Desktop/" + fSrce.getName());
		try {
			success = Utils.copyFile(fSrce, fDest);
		}
		catch (IOException e) {}
		
		if (success)
			Dialogs.showSuccess(
				new Object[] {o}, 
				new String[] {Lang.DIALOG.get("COPY_DESKTOP", "Successfully copied to desktop") + COLON}
			);
		else
			Dialogs.showError(Lang.DIALOG.get("COPY_DESKTOP_ERROR", "Error copying to desktop") + COLON + o.toString());
		
	}
	
	private String promptForSearch() {
		searchDialog.setVisible(true);
		if(searchDialog.isCanceled()) {
			Main.printDebug("Search dialog canceled");
			return null;
		}
		Main.printDebug("Search phrase entered: " + searchDialog.getSearchPhrase());
		return searchDialog.getSearchPhrase();
	}
	
	private boolean searchDocuments(String searchPhrase) {
		if (searchPhrase == null || searchPhrase.trim().equals("")) {
			statusBar.setLabelText(Lang.STATUS_BAR.get("SEARCH_CANCELED", "Search canceled"));
			return false;
		}
		
		/*
		 * Launches a custom application from a special search parameter
		 */
		String trigger = Lang.MISC.getText("CUSTOM_APP", "");
		if (Arrays.asList(trigger.split(" ")).contains(searchPhrase)) {
			Dialogs.showSuccess(DBImages.CUSTOM_WINDOW, Lang.MISC.get("CUSTOM_MSG", "Custom message. See language file for details."));
			String jarPath = Lang.MISC.getText("CUSTOM_JAR", "");
			String className = Lang.MISC.getText("CUSTOM_CLASS", "");
			try {
				Utils.launchClass(jarPath, className);
			}
			catch (Exception e) {
				Dialogs.showError(e, "Error loading " + jarPath+":"+className);
			}
			return false;
		}
		
		
		Main.setCursor(this, Cursor.WAIT_CURSOR);
		
		sendBackAction.setEnabled(false);
		addNotesAction.setEnabled(false);
		renameAction.setEnabled(false);
		//newAction.setEnabled(false);
		deleteAction.setEnabled(false);
		egoAssignAction.setEnabled(true);
		
		printMenuItem.setAction(printFromDBAction);
		printPopupItem.setAction(printFromDBAction);
		editOrViewButton.setAction(viewAction);
		editOrViewPopupItem.setAction(viewAction);
		
		resultListModel.clear();
		
		java.util.List<Document> docList = new ArrayList<Document>();
		Set<WeightedDocument> weightedResults = new TreeSet<WeightedDocument>();
		
		Set<String> wordSet;
		
		if(searchDialog.getMatchMode() == SearchDialog.MATCH_WORDS)
			wordSet = new HashSet<String>(Arrays.asList(searchPhrase.split(" ")));
		else {
			wordSet = new HashSet<String>();
			wordSet.add(searchPhrase);
		}
		
		docList = DBController.searchDocuments(wordSet);
		Collections.sort(docList);

		for(Document d : docList) {
			Integer relevanceCounter = 0;
			for(String searchTerm : wordSet) {
				if (!searchTerm.startsWith("-") && 
					d.getDocumentName().toLowerCase().contains(searchTerm.toLowerCase()))
						relevanceCounter++;
			}
			
			if (relevanceCounter > 0)
				weightedResults.add(new WeightedDocument(d, relevanceCounter));
		}
		
		listWeightedResults(weightedResults);
		resultList.setToolTipText(Lang.TOOL_TIP.get("DETAIL_LIST_DOCS", "Search results"));
		
		if (searchDialog.SEARCH_FILE_SERVERS)
			searchFileServers(wordSet, searchPhrase, weightedResults);
		
		Main.setCursor(this, Cursor.DEFAULT_CURSOR);
		return true;
	}
	
	private void listWeightedResults(Set<WeightedDocument> set) {
		resultListModel.clear();
		String delim = Lang.LISTING.getText("LIST_DELIMETER", "~");
		int prevWeight = -1;
		for(WeightedDocument d : set) {
			if(prevWeight == -1 || d.getWeight() < prevWeight) {
				resultListModel.addElement(delim + " " +
					Lang.LISTING.getText("LIST_CONTAIN", "The Following Documents Contain") + 
					" " + d.getWeight() + " " +
					Lang.LISTING.getText("LIST_CRITERIA", "of Your Search Criteria") +
					" " + delim);
				prevWeight = d.getWeight();
			}
			resultListModel.addElement(d, DocumentResultListModel.Filter.APPROVED);
		}
		
		if (resultListModel.getSize() == 0)
			resultListModel.addElement(delim + " " + 
				Lang.LISTING.getText("LIST_EMPTY", "Your search returned no results") 
				+ " " + delim);
		
		Main.setCursor(this, Cursor.DEFAULT_CURSOR);
		statusBar.setLabelText(resultListModel.getRelevantSize() + " " + 
			Lang.STATUS_BAR.getText("DOCUMENTS_FOUND", "documents found"));
	}
	
	private boolean renameDocument(File oldF, File newF) {
		if (DBController.docExistsInDatabase(newF) && ((DBController.docQuery(oldF)).getDocumentID() != (DBController.docQuery(newF)).getDocumentID())) {
			// NEEDS LANGUAGE SUPPORT ADDED
			JOptionPane.showMessageDialog(null, "Document \"" + newF.getName() + "\" already exists in database.  Please chooser another name.", "Error", JOptionPane.ERROR_MESSAGE);
			return false;
		}
		if (oldF != null && !newF.getName().trim().equals("")) {
			Main.printDebug("Changing name to \"" + newF.getName() + "\"");
			if (oldF.exists() && !oldF.isDirectory()) {
				if (!newF.exists() || oldF.getName().equalsIgnoreCase(newF.getName())) {
					if (!oldF.renameTo(newF)) {
						Dialogs.showError(oldF, Lang.DIALOG.get("RENAME_ERROR", "Error renaming file") + COLON);
						//JOptionPane.showMessageDialog(null, "Error renaming file \"" + oldF.getName() + ".\"", "Error", JOptionPane.ERROR_MESSAGE);
						return false;
					}
					else {
						Main.printDebug("Name changed successfully.");
						return true;
					}
				}
				else {
					// NEEDS LANGUAGE SUPPORT ADDED
					Main.printDebug("File \"" + newF.getName() + "\" already exists.");
					int r = JOptionPane.showConfirmDialog(null, "File \"" + newF.getName() + "\" exists.  Overwrite?", "Confirm overwrite", JOptionPane.OK_CANCEL_OPTION);
					if (r == JOptionPane.OK_OPTION) {
						newF.delete();
						if (!oldF.renameTo(newF)) {
							JOptionPane.showMessageDialog(null, "Error renaming file \"" + oldF.getName() + ".\"", "Error", JOptionPane.ERROR_MESSAGE);
							return false;
						}
						else {
							Main.printDebug("Name changed successfully.");
							return true;
						}
					}
					return false;
				}
			}
			else {
				Main.printDebug("Name change failed.  Reason:  File \"" + oldF.getName() + "\" does not exist.");
				return false;
			}
			
		}
		Main.printDebug("Name change canceled.");
		return false;
	}
	
	/**
	 * Assumes we're looking at search/list all docs
	 * -- Therefore, opens from the document's folder
	 */
	public static ActiveXComponent openDocumentReadOnly(Object o, boolean isVisible) {
		if (o instanceof Document)
			return openDocument(true, ((Document)o).toFile(), isVisible);
		else if (o instanceof File)
			return openDocument(true, (File)o, isVisible);
		else
			return null;
	}
	
	/** 
	 * Assumes we're looking at due/owed docs
	 * -- Therefore, opens from the user's folder
	 */
	public static ActiveXComponent openDocumentEdit(Object o, User u, boolean isVisible) {
		if (o instanceof Document)
			return openDocument(false, ((Document)o).toAssignedFile(u), isVisible);
		else if (o instanceof File)
			return openDocument(false, (File)o, isVisible);
		else
			return null;
	}
	
	/*protected static ActiveXComponent openDocumentAdmin(Object o, User u, boolean isVisible) {
		if (o instanceof Document)
			return openDocument(false, ((Document)o).toAssignedFile(u), isVisible);
		else
			return null;
	}*/
	
	/**
	 * Opens a document represented by a File object.
	 * This function should only be called from one of the openDocumentX() functions above.
	 */
	public static ActiveXComponent openDocument(boolean readOnly, File docFile, boolean isVisible) {
		boolean isAcrobat = DBController.getActiveXCall(docFile).equalsIgnoreCase("Acrobat.Application");
		boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); 
		
		if (!isWindows || isAcrobat) { 
			try {
				Utils.desktopCall("open", docFile);
			}
			catch (Exception e) {
				Dialogs.showError(e, docFile, "Error opening file on this platform.");
			}
			return null;
		}
		return Jacob.openDocument(readOnly, docFile, isVisible);
	}
	
	/**
	 * List the User's Owed files based on user's name
	 */
	private boolean listOwedDocs(String user, Integer index) {
		Main.setCursor(ClientWindow.this, Cursor.WAIT_CURSOR);
		sendBackAction.setEnabled(true);
		addNotesAction.setEnabled(false);
		renameAction.setEnabled(true);
		//newAction.setEnabled(true);
		deleteAction.setEnabled(true);
		egoAssignAction.setEnabled(false);
		
		editOrViewButton.setAction(editAction);
		editOrViewPopupItem.setAction(editAction);
		printMenuItem.setAction(printFromOweAction);
		printPopupItem.setAction(printFromOweAction);
		
		resultList.setToolTipText(Lang.TOOL_TIP.get("DUE_DOCS", "Documents awaiting updating"));
		
		resultListModel.clear();
		
		String delim = Lang.LISTING.getText("LIST_DELIMETER", "~");
		File f = new File(Utils.getUserRoot(currentUser));
		if (!f.isDirectory()) {
			Main.printDebug("Directory does not exists.  Attempting to create...&");
			if (f.mkdir()) 
				Main.printDebug("success.");
			else  {
				Main.printDebug("failed.");
				Main.setCursor(ClientWindow.this, Cursor.DEFAULT_CURSOR);
				return false;
			}
		}
		java.util.List<Document> docs = new ArrayList<Document>();
		for (File i : f.listFiles()) {
			if (DBController.isSupportedFile(i) && !i.getName().startsWith("~")) { 
				Document d = DBController.docQuery(i);
				if (d == null)
					docs.add(Utils.createDocument(i, currentUser));
				else
					docs.add(d);
			}
		}
		
		Collections.sort(docs);
		
		resultListModel.addAll(docs);
		
		resultList.setSelectedIndex(index == null?0:index);
		resultList.requestFocusInWindow();
		
		statusBar.setLabelText("" + resultListModel.getSize() + " " + Lang.STATUS_BAR.getText("DOCUMENTS_LISTED", "documents listed"));
		if (resultListModel.getSize() == 0) {
			resultListModel.addElement(delim + " " + Lang.STATUS_BAR.getText("CAUGHT_UP", "You are currently caught up")  + " " + delim);
		}
		Main.setCursor(ClientWindow.this, Cursor.DEFAULT_CURSOR);
		return true;
	}
	
	private boolean listOwedDocs(String user) {
		return listOwedDocs(user, null);
	}
	
	private boolean listOwedDocs() {
		return listOwedDocs(currentUser.getUserName());
	}

	private void createNewDocument() {
		ViewMode.listMode = ViewMode.EXTENSION_MODE;
		listOwedDocs();
		java.util.List<String> extList = new ArrayList<String>();
		for (String s : DBController.getExtensions())
			if (DBController.supportsCreateNew(s))
				extList.add(s);
			
		String extValue = (String)Dialogs.showListDialog(this, extList);
		if (extValue != null) {
			File dest = new File(Utils.getUserRoot(userName) + Lang.FILE_IO.getText("DOCUMENT_TEMPFILE", "Procedure Template") + "." + extValue);
			try {
				if (!Utils.copyFromJar(".templates/template." + extValue, dest))
					throw new IOException(Lang.DIALOG.getText("JAR_COPY_ERROR", "Error copying from jar")); 
			}
			catch (Exception j) {
				Main.printStackTrace(j, Lang.DIALOG.getText("JAR_COPY_ERROR", "Error copying from jar"));
				return;
			}
			File newFile = promptForRename(dest);
			if (renameDocument(dest, newFile)) {
				if(DBController.addDocument(Utils.createDocument(newFile, userName), userName)) {
					listOwedDocs(userName);
					resultList.setSelectedValue(newFile, true);
					resultList.requestFocusInWindow();
				}
			}
			else
				newFile.delete();
			dest.delete();
		}
	}
	
	private void sendBackDocument(Object o) {
		if (!(o instanceof Document))
			return;
		User u = currentUser;
		Document d = (Document)o;
		String failedProc = "";
		File doneFile = new File(Utils.getDoneRoot(u) + d.getFullName(u));
		String msg = "Successfully sent back document";
		try {
			failedProc = "copying to done/approval folder";
			if (Utils.copyFile(d.toAssignedFile(u), doneFile)) {
				failedProc = "deleting assigned file (file may have sent back properly)";
				DBController.updateDocument(DBController.docQuery(doneFile), currentUser);
				d.toAssignedFile(u).delete();
			}
		}
		catch (Exception e) {
			Dialogs.showError("Send back document failed\n\nReason: " + failedProc + " failed");
			return;
		}
		listOwedDocs(userName, resultList.getSelectedIndex());
		Dialogs.showSuccess(o, msg);
	}
	
	/**
	 * List all Procedures in the database based on a filter to match.
	 * Null lists all documents.
	 */
	private void listAllDocs(String listFilter) {
		sendBackAction.setEnabled(false);
		addNotesAction.setEnabled(false);
		renameAction.setEnabled(false);
		//newAction.setEnabled(false);
		deleteAction.setEnabled(false);
		egoAssignAction.setEnabled(true);
		
		editOrViewButton.setAction(viewAction);
		editOrViewPopupItem.setAction(viewAction);
		printMenuItem.setAction(printFromDBAction);
		printPopupItem.setAction(printFromDBAction);
		
		resultList.setToolTipText("Double-click to open, right click for options");
		resultListModel.clear();
		java.util.List<Document> resultElements = null;
		
		try {
			resultElements = DBController.getAllDocuments();
		}
		catch(SQLException ex) {
			Main.printStackTrace(ex, "SQL error while listing documents. Shutting down");
			closeProgram();
		}
		Collections.sort(resultElements);
		resultListModel.addAll(resultElements, DocumentResultListModel.Filter.APPROVED);
		
		statusBar.setLabelText("" + resultListModel.getSize() + " " + Lang.STATUS_BAR.getText("DOCUMENTS_LISTED", "documents listed"));
		resultList.setSelectedIndex(0);
		resultList.requestFocusInWindow();
	}
}
